package 函数式编程.使用Stream;

Java Stream转List可以直接toList而不必collect了?  2022年5月21日
Stream.toList()和Collectors.toList()的区别

Java 16中的Stream增强，可以直接通过toList()来转换成List。
主要涉及下面这几种转换方式：
·list.stream().toList();
·list.stream().collect(Collectors.toList());
·list.stream().collect(Collectors.toUnmodifiableList());

然后，看到有网友评论问：Stream.toList()和Collectors.toList()的区别是什么？哪个性能好？

处理结果的区别：

·Stream.toList()返回的List是不可变List，不能增删改
·Collectors.toList()返回的是个普通的List，可以增删改
·Collectors.toUnmodifiableList()返回的List是不可变List，不能增删改


“为啥你的stream可以直接toList而不必collect？” 下面就给大家解读下这个内容。

疑问的代码片段如下：

public class StreamTest {

    @Test
    void test() {
        List<String> list = List.of("blog.didispace.com", "spring4all.com", "openwrite.cn", "www.didispace.com");

        List<String> result = list.stream()
                .filter(e -> e.contains("didispace.com"))
                .filter(e -> e.length() > 17)
                .toList();

        System.out.println(result);
    }

}
小伙伴疑问的就是第37行：toList()。实际上这个方法是Java 16才支持的一个方法，它可以直接将Stream转化成List。而因为目前很多小伙伴还在用Java 8，所以在
介绍如何调试Stream的时候，直接用我这段代码可能会碰到这个问题。

那么Java 8的用户怎么写呢？我看到也有网友直接给出了Java 8下的方法，就如下面这样：

List<String> result = list.stream()
    .filter(e -> e.contains("didispace.com"))
    .filter(e -> e.length() > 17)
    .collect(Collectors.toList());

#Stream.toList()和Collectors.toList()的区别
就完整上面的代码逻辑，这样的替换完全是可以的，但是虽然最终都转成List了，他们之间是否还有区别呢？

这里我单独拉出来说，显然肯定是有区别的。

通过查看Stream.toList()的源码：

default List<T> toList() {
    return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));
}
我们可以发现，它所创建的是一个unmodifiableList不可变的List。

而使用Stream.collect(Collectors.toList())创建出来的则是一个普通的List，是可以做增删改操作的。

那么如果用Collectors也要创建不可变的List要怎么写呢？其实也很简单，只需要调用Collectors.toUnmodifiableList()就可以了。
所以与本文开头等价代码替换可以这样写：

List<String> result = list.stream()
    .filter(e -> e.contains("didispace.com"))
    .filter(e -> e.length() > 17)
    .collect(Collectors.toUnmodifiableList());
但要注意的是，这个方法Java 8里也没有，是Java 10才开始支持的。